﻿// <copyright file="FirefoxBrowserLanguagePreference.cs" company="None">(c) Guy Smith-Ferrier, 2012</copyright>

namespace Browser
{
    using System;
    using System.IO;
    using System.Runtime.InteropServices;

    /// <summary>
    /// FirefoxBrowserLanguagePreference is a class to get and/or set the FireFox Language Preference
    /// </summary>
    /// <remarks>FireFox must not be running in order to set the language preference (because FireFox does not re-read its settings and it writes them
    /// back out when it closes thereby overwriting the changes made by this class).</remarks>
    public class FirefoxBrowserLanguagePreference : IBrowserLanguagePreference
    {
        /// <summary>
        /// Gets or sets the browser's language preferences
        /// </summary>
        public string LanguagePreferences
        {
            get
            {
                string javaScript = this.JavaScriptContents;

                // look for a line like this:-
                // user_pref("intl.accept_languages", "en-gb, en,ar-om");
                int index = javaScript.IndexOf(@"user_pref(""intl.accept_languages"",");
                if (index == -1)
                {
                    return null;
                }

                string languagePreferences = javaScript.Substring(index + 34).TrimStart();
                index = languagePreferences.IndexOf(")");
                if (index == -1)
                {
                    return null;
                }

                languagePreferences = languagePreferences.Substring(0, index - 1).TrimEnd().Replace(@"""", string.Empty).Replace(" ", string.Empty);

                return languagePreferences;
            }

            set
            {
                string javaScript = this.JavaScriptContents;

                // look for a line like this:-
                // user_pref("intl.accept_languages", "en-gb, en,ar-om");
                int startIndex = javaScript.IndexOf(@"user_pref(""intl.accept_languages"",");
                if (startIndex > -1)
                {
                    startIndex += 36;

                    string remainingJavaScript = javaScript.Substring(startIndex).TrimStart();
                    int finishIndex = remainingJavaScript.IndexOf(")");
                    if (finishIndex > -1)
                    {
                        javaScript = javaScript.Substring(0, startIndex) + value + remainingJavaScript.Substring(finishIndex - 1);

                        this.JavaScriptContents = javaScript;
                    }
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether the browser exists on this computer
        /// </summary>
        public bool BrowserExists
        {
            get
            {
                return Directory.Exists(this.FirefoxPath);
            }
        }

        /// <summary>
        /// Gets the file path to the Firefox browser's data
        /// </summary>
        private string FirefoxPath
        {
            get
            {
                // e.g. C:\Users\<user name>\AppData\Roaming\Mozilla\Firefox
                return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Mozilla\Firefox");
            }
        }

        /// <summary>
        /// Gets the file path to the Firefox browser's INI file
        /// </summary>
        private string ProfilesIniPath
        {
            get
            {
                // e.g. C:\Users\<user name>\AppData\Roaming\Mozilla\Firefox\profiles.ini
                return Path.Combine(this.FirefoxPath, "profiles.ini");
            }
        }

        /// <summary>
        /// Gets the path to the Firefox browser's prefs.js file
        /// </summary>
        private string PrefsjsPath
        {
            get
            {
                string returnString = new string(' ', 32768);
                GetPrivateProfileString("Profile0", "Path", null, returnString, 32768, this.ProfilesIniPath);
                
                // this should be something like "Profiles/r3ygjtlt.default"
                string relativeDefaultProfilePath = returnString;
                int index = relativeDefaultProfilePath.IndexOf('\0');
                if (index > -1)
                {
                    relativeDefaultProfilePath = relativeDefaultProfilePath.Substring(0, index);
                }

                string fullDefaultProfilePath = Path.Combine(this.FirefoxPath, relativeDefaultProfilePath.Replace("/", Path.DirectorySeparatorChar.ToString()));

                // e.g. C:\Users\<user name>\AppData\Roaming\Mozilla\Firefox\Profiles\r3ygjtlt.default\prefs.js
                return Path.Combine(fullDefaultProfilePath, "prefs.js");
            }
        }

        /// <summary>
        /// Gets or sets the contents of the Prefs file
        /// </summary>
        private string JavaScriptContents
        {
            get
            {
                string javaScriptContents;
                using (TextReader reader = new StreamReader(this.PrefsjsPath))
                {
                    javaScriptContents = reader.ReadToEnd();

                    reader.Close();
                }

                return javaScriptContents;
            }

            set
            {
                using (TextWriter writer = new StreamWriter(this.PrefsjsPath))
                {
                    writer.Write(value);

                    writer.Close();
                }
            }
        }

        [DllImport("KERNEL32.DLL", EntryPoint = "GetPrivateProfileStringW",
            SetLastError = true,
            CharSet = CharSet.Unicode, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        private static extern int GetPrivateProfileString(
          string appName,
          string keyName,
          string defaultValue,
          string returnString,
          int size,
          string filename);
    }
}
